page->flags &= ~PG_type_mask;
page->flags |= PGT_writeable_page;
}
- page->flags &= ~PG_noflush;
+ page->flags |= PG_need_flush;
get_page_type(page);
}
ASSERT(DOMAIN_OKAY(page->flags));
ASSERT((!writeable) ||
((page_type_count(page) != 0) &&
- ((page->flags & PG_type_mask) == PGT_writeable_page)));
+ ((page->flags & PG_type_mask) == PGT_writeable_page) &&
+ ((page->flags & PG_need_flush) == PG_need_flush)));
if ( writeable && (put_page_type(page) == 0) )
+ {
tlb_flush[smp_processor_id()] = 1;
+ page->flags &= ~PG_need_flush;
+ }
put_page_tot(page);
}
{
if ( page->type_count == 0 )
{
- page->flags &= ~PG_type_mask;
+ page->flags &= ~(PG_type_mask | PG_need_flush);
/* NB. This ref alone won't cause a TLB flush. */
- page->flags |= PGT_writeable_page | PG_noflush;
+ page->flags |= PGT_writeable_page;
}
get_page_type(page);
}
page = frame_table + pfn;
if ( writeable_buffer &&
(put_page_type(page) == 0) &&
- !(page->flags & PG_noflush) )
+ (page->flags & PG_need_flush) )
{
__flush_tlb();
+ page->flags &= ~PG_need_flush;
}
- page->flags &= ~PG_noflush;
put_page_tot(page);
}
spin_unlock_irqrestore(&p->page_lock, flags);
#define PGT_net_rx_buf (8<<24) /* this page has been pirated by the net code. */
/*
- * This bit is sometimes set by Xen when it holds a writeable reference to a
- * page that shouldn't cause a TLB flush when it is dropped. For example, a
- * disk write to a page with initial type_count == 0, which returns to 0 after
- * the I/O. In this case, we'd normally flush the TLB because a writeable page
- * has just lost its mutually-exclusive type. But this isn't necessary here
- * because the writeable reference never made it into user-accessible TLB
- * (didn't make it into TLB at all, in fact).
+ * This bit indicates that the TLB must be flushed when the type count of this
+ * frame drops to zero. This is needed on current x86 processors only for
+ * frames which have guestos-accessible writeable mappings. In this case we must
+ * prevent stale TLB entries allowing the frame to be written if it used for a
+ * page table, for example.
*
- * This bit is obviously nuked in a few places, for safety.
+ * We have this bit because the writeable type is actually also used to pin a page
+ * when it is used as a disk read buffer. This doesn't require a TLB flush because
+ * the frame never has a mapping in the TLB.
*/
-#define PG_noflush (1<<28)
+#define PG_need_flush (1<<28)
#define PageSlab(page) test_bit(PG_slab, &(page)->flags)
#define PageSetSlab(page) set_bit(PG_slab, &(page)->flags)